{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "flare is a teacher in ai industry. He obtained his phd in Australia. Australia is a country in the Southern Hemisphere.\n"
     ]
    }
   ],
   "source": [
    "data = open('flare').read()\n",
    "print(data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'.', 'o', 'i', 'd', 'f', 'r', 'H', 'b', 'p', 's', 'y', 'h', 'l', 't', 'u', 'e', 'S', 'm', 'A', ' ', 'n', 'a', 'c'} 23\n"
     ]
    }
   ],
   "source": [
    "letters = set(data)\n",
    "num_letters = len(letters)\n",
    "print(letters,num_letters)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'.': 0, 'o': 1, 'i': 2, 'd': 3, 'f': 4, 'r': 5, 'H': 6, 'b': 7, 'p': 8, 's': 9, 'y': 10, 'h': 11, 'l': 12, 't': 13, 'u': 14, 'e': 15, 'S': 16, 'm': 17, 'A': 18, ' ': 19, 'n': 20, 'a': 21, 'c': 22}\n",
      "{0: '.', 1: 'o', 2: 'i', 3: 'd', 4: 'f', 5: 'r', 6: 'H', 7: 'b', 8: 'p', 9: 's', 10: 'y', 11: 'h', 12: 'l', 13: 't', 14: 'u', 15: 'e', 16: 'S', 17: 'm', 18: 'A', 19: ' ', 20: 'n', 21: 'a', 22: 'c'}\n"
     ]
    }
   ],
   "source": [
    "#dictionary\n",
    "int_2_letter = {a:b for a,b in enumerate(letters)}\n",
    "letter_2_int = {b:a for a,b in enumerate(letters)}\n",
    "print(char2num)\n",
    "print(num2char)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "#set length of the sequence\n",
    "sequence_length = 20"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [],
   "source": [
    "#基于输入字符串，自动生成one-hot数据\n",
    "#调用格式：generate(batch_size,genarate_num)\n",
    "#batch_size表示数据生成器每个批次有几组数据；\n",
    "#generate_num表示数据生成器生成数据次数\n",
    "import numpy as np\n",
    "from keras.utils import to_categorical\n",
    "#字符到数字的批量转化\n",
    "def words_2_ints(words):\n",
    "    ints = []\n",
    "    for itmp in words:\n",
    "        ints.append(letter_2_int[itmp])\n",
    "    return ints\n",
    " #数字转为one-hot格式\n",
    "def words_2_one_hot(words, num_classes=num_letters):\n",
    "    return to_categorical(words_2_ints(words), num_classes=num_classes)\n",
    "#获取one-hot格式数据对应数值\n",
    "def get_one_hot_max_idx(one_hot):\n",
    "    idx_ = 0\n",
    "    max_ = 0\n",
    "    for i in range(len(one_hot)):\n",
    "        if max_ < one_hot[i]:\n",
    "            max_ = one_hot[i]\n",
    "            idx_ = i\n",
    "    return idx_\n",
    "#one-hot数据转字符\n",
    "def one_hot_2_words(one_hot):\n",
    "    tmp = []\n",
    "    for itmp in one_hot:\n",
    "        tmp.append(int_2_letter[get_one_hot_max_idx(itmp)])\n",
    "    return \"\".join(tmp)\n",
    " \n",
    "def genarate_data(batch_size=100, genarate_num=-1):\n",
    "    cnt = 0\n",
    "    batch_x = []\n",
    "    batch_y = []\n",
    "    sample_num = 0\n",
    "    while(True):\n",
    "        for i in range(len(data) - sequence_length):\n",
    "            batch_x.append(words_2_one_hot(data[i : i+sequence_length]))\n",
    "            batch_y.append(words_2_one_hot(data[i+sequence_length])[0]) #这里数据加[0]，是为了符合keras的输出数据格式。 因为不加[0]，表示是3维的数据。 你可以自己尝试不加0，看下面的test打印出来是什么\n",
    "            sample_num += 1\n",
    "            #print('sample num is :', sample_num)\n",
    "            if len(batch_x) == batch_size:\n",
    "                yield (np.array(batch_x), np.array(batch_y))\n",
    "                batch_x = []\n",
    "                batch_y = []\n",
    "                if genarate_num != -1:\n",
    "                    cnt += 1 \n",
    "                if cnt == genarate_num:\n",
    "                    return"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<generator object genarate_data at 0x000002CB5F054B48>\n"
     ]
    }
   ],
   "source": [
    "a = genarate_data(batch_size=1,genarate_num=1)\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(array([[[0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 1., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 1.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.],\n",
      "        [0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 1., 0., 0., 0.],\n",
      "        [0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "         0., 0., 0., 0., 0., 0., 0.]]], dtype=float32), array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.,\n",
      "        0., 0., 0., 0., 1., 0., 0.]], dtype=float32))\n"
     ]
    }
   ],
   "source": [
    "for i in genarate_data(batch_size=1,genarate_num=1):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [],
   "source": [
    "#set up the model\n",
    "from keras.models import Sequential\n",
    "from keras.layers import Dense,LSTM,SimpleRNN\n",
    "\n",
    "model = Sequential()\n",
    "model.add(SimpleRNN(units=30,input_shape=(sequence_length,num_letters),activation='linear'))\n",
    "model.add(Dense(units=num_letters,activation='softmax'))\n",
    "model.compile(optimizer='adam',loss='categorical_crossentropy',metrics=['accuracy'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/10\n",
      "10/10 [==============================] - 0s 30ms/step - loss: 3.1850 - accuracy: 0.0560\n",
      "Epoch 2/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 2.8168 - accuracy: 0.1470\n",
      "Epoch 3/10\n",
      "10/10 [==============================] - 0s 10ms/step - loss: 2.5098 - accuracy: 0.2810\n",
      "Epoch 4/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 2.1919 - accuracy: 0.3700\n",
      "Epoch 5/10\n",
      "10/10 [==============================] - 0s 10ms/step - loss: 1.8471 - accuracy: 0.4560\n",
      "Epoch 6/10\n",
      "10/10 [==============================] - 0s 10ms/step - loss: 1.4497 - accuracy: 0.5540\n",
      "Epoch 7/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 1.0425 - accuracy: 0.6490\n",
      "Epoch 8/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 0.6396 - accuracy: 0.8180\n",
      "Epoch 9/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 0.2965 - accuracy: 0.9620\n",
      "Epoch 10/10\n",
      "10/10 [==============================] - 0s 9ms/step - loss: 0.0934 - accuracy: 1.0000\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<keras.callbacks.callbacks.History at 0x2cb62a65f28>"
      ]
     },
     "execution_count": 54,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.fit_generator(genarate_data(),epochs=10,steps_per_epoch=10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test = 'flare is a teacher i'\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
